package futbol.tacticas.concursantes2007.SeteTeam.jugadores;

import futbol.tacticas.concursantes2007.SeteTeam.jugadores.facklab.Entrenador;
import futbol.tacticas.concursantes2007.SeteTeam.jugadores.geometria.Linea;

import java.util.Vector;

import java.awt.Point;

import futbol.tacticas.*;


/**
 * Clase abstracta que espcefica las funciones basicas
 * de un jugador y la cual deben heredar todos los
 * jugadores de nuestro equipo
 * 
 * @author llua
 *
 */
public abstract class AbstractTacticaJugador {
	
	//Numero del jugador
	private final transient int numero;
	
	//Posicion x inicial del jugador
	private final transient int xInicial;
	
	//Posicion y inicial del jugador
	private final transient int yInicial;
	
	//Fuerza del jugador
	private final transient int fuerza;
	
	//Entrenador que toma de referencia el jugador
	private final transient Entrenador entrenador;
	
	/**
	 * Constructor unico de la clase con los parametros fijos de un jugador
	 * 
	 * @param numero Numero del jugador
	 * @param xInicial Posicion x inicial del jugador
	 * @param yInicial Posicion y inicial del jugador
	 * @param fuerza Fuerza del jugador
	 * @param entrenador {@link Entrenador} que toma de referencia el jugador
	 */
	public AbstractTacticaJugador(final int numero, final int xInicial, final int yInicial, final int fuerza, final Entrenador entrenador) {
		super();
		this.numero = numero;
		this.xInicial = xInicial;
		this.yInicial = yInicial;
		
		//Segun la normativa la fuerza se situa entre 4-7
		if(fuerza>7){
			this.fuerza = 7;
		}else if(fuerza<4){
			this.fuerza = 4;
		}else{
			this.fuerza = fuerza;
		}
		
		this.entrenador = entrenador;
	}
	
	/**
	 * Este metodo llama a los metodos gererarTactica y generarAccion
	 * a los cuales se les pasara el {@link Vector} compuesto por {@link Comando}
	 * para que lo rellenen.
	 * 
	 * @param comandos {@link Vector} compuesto por {@link Comando}
	 */
	public void generarTactica(final Vector<Comando> comandos){
		generarMovimiento(comandos);
		generarAccion(comandos);
	}
	
	/**
	 * Metodo abstracto cullo proposito es el de definir aquellos comandos del jugador
	 * que hagan referencia a su posicion 
	 * 
	 * @param comandos {@link Vector} compuesto por {@link Comando}
	 */
	abstract protected void generarMovimiento(final Vector<Comando> comandos);
	
	/**
	 * Metodo abstracto cullo proposito es el de definir aquellos comandos del jugador
	 * que hagan referencia a sus acciones sobre la bola 
	 * 
	 * @param comandos {@link Vector} compuesto por {@link Comando}
	 */
	abstract protected void generarAccion(final Vector<Comando> comandos);
	
	/** 
	 * Recoge la fuerza
	 * 
	 * @return fuerza
	 */
	public int getFuerza() {
		return fuerza;
	}

	/** 
	 * Recoge la xInicial
	 * 
	 * @return xInicial
	 */
	public int getXInicial() {
		return xInicial;
	}

	/** 
	 * Recoge la yInicial
	 * 
	 * @return yInicial
	 */
	public int getYInicial() {
		return yInicial;
	}

	/** 
	 * Recoge el numero
	 * 
	 * @return numero
	 */
	public int getNumero() {
		return numero;
	}

	/** 
	 * Recoge el {@link Entrenador}
	 * 
	 * @return {@link Entrenador}
	 */
	protected Entrenador getEntrenador() {
		return entrenador;
	}
	
	/** 
	 * Recoge la {@link SituacionJugadores} del entrenador
	 * 
	 * @return {@link SituacionJugadores}
	 */
	protected SituacionJugadores getSituacion() {
		// Comentario de prueba
		return entrenador.getSituacion();
	}
	
	/** 
	 * Devuelve true si es el jugador mas cercano a la bola
	 * 
	 * @return boolean
	 */
	protected boolean isJugadorMasCercanoBola() {
		return getSituacion().getMasCercanoDeBola()==numero;
	}
	
	protected Point getPosicion() {
		return getSituacion().getMisJugadores()[numero];
	}
	
	/**
	 * Devuelve la posicio del jugador enemigo mas cercano
	 * 
	 * @return Enemigo mas cercano
	 */
	protected Point getEnemigoMasCercano() {
		final int nenemigoCerca = getSituacion().getContrarioMasCerca(getNumero());
		return getSituacion().getContrario()[nenemigoCerca];
	}
	
	//---------------COMANDOS--------------------
	
	/**
	 * Genera un {@link ComandoIrA} refereciado al jugador
	 * 
	 * @param x
	 * @param y
	 * @return {@link Comando}
	 */
	protected Comando irA(double x,double y) {
		if (y>120)  y=120;
		if (y<-120) y=-120;
		if (x>160)  x=160;
		if (x<-160) x=-160;
		return new ComandoIrA(numero,x,y);
	}
	
	/**
	 * Genera un {@link ComandoIrA} que mueve al jugador a su
	 * posicion inicial
	 * 
	 * @return {@link Comando}
	 */
	protected Comando irAPosicionInicial() {
		//final Rectangulo area = getArea();
		
		int x = xInicial;
		int y = yInicial;
		
	
		//if (y>area.getA().getY()) y =(int)area.getA().getY();
		//if (y<area.getB().getY()) y =(int)area.getB().getY();
		//if (x>area.getA().getX()) x =(int)area.getA().getX();
		//if (x<area.getB().getX()) x =(int)area.getB().getX();
		
		//if (y>120)  y=120;
		//if (y<-120) y=-120;
		//if (x>160)  x=160;
		//if (x<-160) x=-160;
		
		return new ComandoIrA(numero,x,y);
	}
	
	/**
	 * Genera un {@link ComandoGolpearBola} refereciado al jugador
	 * 
	 * @param x
	 * @param y
	 * @return {@link Comando}
	 */
	protected Comando golpearBola(final double x, final double y){
		return new ComandoGolpearBola(numero,x,y);
	}
	
	/**
	 * Genera un {@link ComandoPase} refereciado al jugador
	 * 
	 * @param x
	 * @param y
	 * @return {@link Comando}
	 */
	protected Comando pase(final int jugador){
		return new ComandoPase(numero,jugador);
	}
	
	/**
	 * Genera un {@link ComandoTiroAPuerta} refereciado al jugador
	 * 
	 * @param x
	 * @param y
	 * @return {@link Comando}
	 */
	protected Comando tiroAPuerta(final int desvio){
		return new ComandoTiroAPuerta(numero,desvio);
	}
	
	/**
	 * Genera un {@link ComandoGolpearBola} refereciado al jugador que va 
	 * dirigido a la posicion mas vulnerable de la porteria;
	 * 
	 * @param x
	 * @param y
	 * @return {@link Comando}
	 */
	protected Comando tiroAPuertaPreciso(){
		Point temp = entrenador.getPuntoDebilPorteria();
		return new ComandoTiroAPuerta(numero,temp.y);
	}
	
	private int evaluacion(final Point a) {
		final Point b = getEntrenador().getPuntoDebilPorteria();
		final Point c = getSituacion().getBola();
		
		int evaluacionTiro  = Densidad_Jugadores(a,b);
		int evaluacionPase  = Densidad_Jugadores(a,c);
		
		return (evaluacionPase + evaluacionTiro);
	}    

	public Point heuristicaMovimiento(Point a, Point b) {
		Point solucion = a;
		
		// Esta es la tasa de incremento, la velocidad
		// del juego depende de este valor.
		final int tasa = 5; 
		
		for(int x=a.x; x<=b.x; x=x+tasa){
			for(int y=a.y; y<=b.y; y=y+tasa){
				Point aux = new Point(x,y);
				if (evaluacion(aux)<evaluacion(solucion)){
					solucion = aux;
				}
			}	
		}

		return solucion;
	}


    public int Densidad_Jugadores(Point a, Point b){

        ////////////////////////////////////////////////////////////
        // Esta funcin me indica el nmero de jugadores del equipo
        // contrario que hay entre dos de mis jugadores.
        ////////////////////////////////////////////////////////////
    	
    	Point Mi_rival[] =getSituacion().getContrario();
        
    	int jugadores = 0;
        double Cota = 10.0;
    	
        for(Point z : Mi_rival){
            double k = a.distance(b);
            if ((z.distance(a)<k) && (z.distance(b)<k)){
            	Linea linea = new Linea(a,b);
            	if (linea.calcularDistancia(z)<Cota){
            		jugadores++;
            	}
            }
        }
        
        return jugadores;
    }

}
